Skip to content

fix(update-major-tag): guard major tag push against concurrent rewinds#235

Merged
bedatty merged 1 commit intodevelopfrom
fix/update-major-tag-lease
Apr 17, 2026
Merged

fix(update-major-tag): guard major tag push against concurrent rewinds#235
bedatty merged 1 commit intodevelopfrom
fix/update-major-tag-lease

Conversation

@bedatty
Copy link
Copy Markdown
Contributor

@bedatty bedatty commented Apr 17, 2026

Lerian

GitHub Actions Shared Workflows


Description

Fixes a TOCTOU race flagged by CodeRabbit on PR #233 for the floating-major-tag update composite (src/config/update-major-tag/action.yml).

Problem

self-release.yml and release.yml do not define a concurrency: block, so two release runs on main (e.g. back-to-back merges) can overlap. If run A resolves LATEST=v1.26.0 while run B resolves LATEST=v1.27.0 and finishes its push first (moving v1 → def), run A's subsequent git push --force would silently rewind v1 back to abc (v1.26.0). Consumers pinning to @v1 would regress until the next release.

Fix

Replace the unconditional --force with --force-with-lease, reading the current remote SHA via git ls-remote first:

REMOTE_MAJOR_SHA=$(git ls-remote --refs --tags origin "refs/tags/$MAJOR" | awk '{print $1}')
LEASE_SHA="${REMOTE_MAJOR_SHA:-0000000000000000000000000000000000000000}"
git push origin "refs/tags/$MAJOR:refs/tags/$MAJOR" \
  --force-with-lease="refs/tags/$MAJOR:$LEASE_SHA"

If another run advanced $MAJOR between the lease read and the push, the push fails loudly instead of rewinding the tag. The zero-SHA fallback handles the first-ever push (tag not yet present on remote).

Affected file:

  • src/config/update-major-tag/action.yml

Type of Change

  • feat: New workflow or new input/output/step in an existing workflow
  • fix: Bug fix in a workflow (incorrect behavior, broken step, wrong condition)
  • perf: Performance improvement (e.g. caching, parallelism, reduced steps)
  • refactor: Internal restructuring with no behavior change
  • docs: Documentation only (README, docs/, inline comments)
  • ci: Changes to self-CI (workflows under .github/workflows/ that run on this repo)
  • chore: Dependency bumps, config updates, maintenance
  • test: Adding or updating tests
  • BREAKING CHANGE: Callers must update their configuration after this PR

Breaking Changes

None. The lease-based push succeeds in every case the previous unconditional --force did, except when a concurrent run has already advanced the tag — which is exactly the scenario we want to detect and abort.

Testing

  • YAML syntax validated locally
  • Triggered a real workflow run on a caller repository using @develop or the beta tag
  • Verified all existing inputs still work with default values
  • Confirmed no secrets or tokens are printed in logs
  • Checked that unrelated workflows are not affected

Caller repo / workflow run: Next main release in this repo will exercise the composite end-to-end (self-release.yml is the only caller).

Related Issues

Related to #233 — surfaced by CodeRabbit review on that PR.

Summary by CodeRabbit

  • Chores
    • Enhanced the safety of the major tag update workflow by replacing unconditional force push with a lease-based mechanism that validates remote state before pushing, reducing the risk of concurrent conflicts.

@bedatty bedatty requested a review from a team as a code owner April 17, 2026 20:23
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 17, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ab656cc5-8d5c-4be5-93cc-99f30f76dd31

📥 Commits

Reviewing files that changed from the base of the PR and between a714b98 and 3adfa34.

📒 Files selected for processing (1)
  • src/config/update-major-tag/action.yml

Walkthrough

Replaced forced push operation with lease-based force push for major tag updates. Workflow now queries remote commit SHA for the major tag via git ls-remote, derives lease SHA with zero-value fallback, and uses it to validate expected remote state before push.

Changes

Cohort / File(s) Summary
Major Tag Push Safety
src/config/update-major-tag/action.yml
Switched from git push --force to git push --force-with-lease=refs/tags/$MAJOR:$LEASE_SHA. Added git ls-remote query to fetch current remote commit SHA, fallback to all-zero SHA if tag absent, preventing accidental overwrites of concurrent tag modifications.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: replacing unconditional git push --force with --force-with-lease to prevent concurrent tag rewinds.
Description check ✅ Passed The description covers all required template sections: problem statement, technical fix with code, affected files, type of change (fix), breaking changes (none), testing verification, and related issues.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/update-major-tag-lease

Comment @coderabbitai help to get the list of available commands and usage tips.

@lerian-studio lerian-studio added the size/XS PR changes < 50 lines label Apr 17, 2026
@lerian-studio
Copy link
Copy Markdown
Contributor

🔍 Lint Analysis

Check Files Scanned Status
YAML Lint 1 file(s) ✅ success
Action Lint no changes ⏭️ skipped
Pinned Actions 1 file(s) ✅ success
Markdown Link Check no changes ⏭️ skipped
Spelling Check 1 file(s) ✅ success
Shell Check 1 file(s) ✅ success
README Check 1 file(s) ✅ success
Composite Schema 1 file(s) ✅ success
Deployment Matrix no changes ⏭️ skipped

🔍 View full scan logs

@lerian-studio
Copy link
Copy Markdown
Contributor

🛡️ CodeQL Analysis Results

Languages analyzed: actions

✅ No security issues found.


🔍 View full scan logs | 🛡️ Security tab

@bedatty bedatty merged commit 66e40fa into develop Apr 17, 2026
18 checks passed
@github-actions github-actions bot deleted the fix/update-major-tag-lease branch April 17, 2026 20:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XS PR changes < 50 lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants